#ifndef YVM_METHODAREA_H
#define YVM_METHODAREA_H

#include <algorithm>
#include <cstring>
#include <mutex>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "../classfile/ClassFile.h"

using namespace std;

class Interpreter;
class JavaClass;
class ConcurrentGC;

//--------------------------------------------------------------------------------
// Method area has responsible to manage all JavaClass objects. A complete
// lifecycle of java class consists of loading class into jvm, linking those
// loaded JavaClass which would initialize its static fields and finally
// initializing them. findJavaClass() used to check if there is a specific
// JavaClass existed in global class table.
// 方法区负责管理所有 JavaClass 对象。 java类的完整生命周期包括将类加载到 jvm 中，
// 链接那些将初始化其静态字段并最终初始化它们的加载的 JavaClass。
// findJavaClass() 用于检查全局类表中是否存在特定的 JavaClass。
//--------------------------------------------------------------------------------
class MethodArea {
    friend class ConcurrentGC;

public:
    //方法区需要从运行时目录中搜索相关的*.c1ass文件
    MethodArea(const vector<string>& libPaths);
    ~MethodArea();

    //查看一个类是否存在
    JavaClass* findJavaClass(const string& jcName);
    //加载jcName类
    bool loadJavaClass(const string& jcName);
    //移除jcName (该方法用于垃圾回收器)
    bool removeJavaClass(const string& jcName);
    //链接jcName类，初始化static字段
    void linkJavaClass(const string& jcName);
    //初始化jcName，初始化静态字段，调用static{}
    void initJavaClass(Interpreter& exec, const string& jcName);

public:
    //辅助方法，如果不存在jcName则加载
    JavaClass* loadClassIfAbsent(const string& jcName);
    //如果未链接jcName则链接
    void linkClassIfAbsent(const string& jcName);
    //如果未初始化jcName则初始化
    void initClassIfAbsent(Interpreter& exec, const string& jcName);

private:
    const string parseNameToPath(const string& name);

private:
    recursive_mutex maMutex;

    unordered_set<string> linkedClasses;
    unordered_set<string> initedClasses;
    unordered_map<string, JavaClass*> classTable;

    vector<string> searchPaths;
};

#endif  // YVM_METHODAREA_H
